#ifndef MESH_H
#define MESH_H

class Face;
class Shader;
class Material;
class Triangle;

#include "Troll3D_global.h"
#include "GeoTool/vec4.h"

#include "Material.h"
#include "VertexTemplate.h"

#include "Vertex.h"
#include "Image.h"
#include "Triangle.h"

#include <vector>
#include <string>
#include <QDebug>

/*! @brief Explications :
 *
 *  Un mesh sert tout simplement à enregistrer des sommets et leurs liaisons de manière
 *  à les afficher, suivant les particularités d'une primitive (Triangle, Line etc)
 *
 *  Cependant, la particularité de GLSL est de permettre au programmeur de définir soit même
 *  la nature d'un sommet, décomposé en "attribut".
 *
 *  Beaucoup de moteur graphique définissent "en dur" la structure d'un sommet, en
 *  utilisant les attributs les plus communs, tel que la position, la couleur,
 *  les normales et les coordonnées de texture.
 *
 *  Cependant, pour rendre cette librairie la plus proche possible de la philosophie d'OpenGL,
 *  les sommets sont divisé en "attributs". Un attribut est représenté par un "nom", par le
 *  nombre de GLfloat par sommet (vec4, vec3, vec2), ainsi que l'identifiant GLSL.
 *
 *  Cependant, pour éviter d'invoquer la commande glDraw d'openGL à chaque sommet, une
 *  limitation est à suivre : Un Mesh ne peut contenir des sommets que de la même "structure".
 *  Ainsi, le Mesh m1 devra, avant d'insérer un sommet, préciser la "forme" qu'auront ses sommets.
 *
 *  Pour se faire, il doit invoquer la méthode SetVertexTemplate().
 *
 *  Le Vertex Template, comme son nom l'indique, permet de définir la liste des attributs
 *  autorisé par les sommets du mesh.
 *
 *  vertexTemplate = mesh->SetVertexTemplate();
    vertexTemplate->AddAttribute(4, "position");
    vertexTemplate->AddAttribute(4,"color");
    vertexTemplate->AddAttribute(4,"normal");
    vertexTemplate->AddAttribute(4,"texCoord1");


    Vertex *v1 = mesh->NewVertex();
    v1->SetAttribute("position", -1.0, -1.0, -1.0, 1.0);
    v1->SetAttribute("color", 1.0, 0.0, 0.0, 1.0);
    v1->SetAttribute("normal", 0.0, 0.0, 0.0, 1.0);
    v1->SetAttribute("texCoord1",0.0, 0.0, 0.0, 0.0);
 */
class TROLL3DSHARED_EXPORT Mesh
{
    /*******************************
    /*          Public
    /*******************************/
     public :

        /*******************************
        /*          Constructors
        /*******************************/

            Mesh();
            Mesh(VertexTemplate * vt);

        /*******************************
        /*          Methods
        /*******************************/

            void    Display();

            void    RemoveTriangle(int pos);

            void    NewTriangle(Vertex &v1, Vertex &v2, Vertex &v3);

            /*******************************
            /*          Get
            /*******************************/

                VertexTemplate &    GetVertexTemplate();

            /*******************************
            /*          Set
            /*******************************/

            /*******************************
            /*          Static
            /*******************************/

                static Mesh &   Rect2D(float width, float height, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   Rect3D(float width, float height, float depth, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   Sphere(float radius, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   Circle(float radius, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   Cylinder(float radius, float height, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   Grid(int countX, int countZ, float offsetX, float offsetZ, VertexTemplate & vertexTemplate, int position,
                                     int color, int texCoord, int normal);

                static Mesh &   LoadOBJ(const char * filePath, VertexTemplate & vertexTemplate, int position,
                                        int color, int normal, int texCoord);

        /*******************************
        /*          Properties
        /*******************************/

            /*******************************
            /*          Static
            /*******************************/

                static vector<Mesh*>    Meshes;
                static int              TotalAttributes;


    /*******************************
    /*          Private
    /*******************************/
     private :

        /*******************************
        /*          Methods
        /*******************************/

            void UpdateTriangles();

        /*******************************
        /*          Properties
        /*******************************/

            VertexTemplate *        m_VertexTemplate;
            std::vector<Triangle *> m_Triangles;

};

#endif
